package chances.wechat.controller;

import java.awt.Dimension;
import java.io.File;
import java.io.IOException;
import java.io.OutputStream;
import java.net.MalformedURLException;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import javax.servlet.http.HttpServletRequest;

import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import chances.framework.ufs.UserDirectory;
import chances.framework.ufs.UserFile;
import chances.framework.ufs.UserFileSystem;
import chances.utils.ImageUtils;
import chances.wechat.api.MediaAPI;
import chances.wechat.api.TokenFactory;
import chances.wechat.data.PageBean;
import chances.wechat.entity.UserMedia;
import chances.wechat.entity.WechatUser;
import chances.wechat.resp.ResultResponse;
import chances.wechat.resp.ResultSetResponse;
import chances.wechat.service.UserMediaService;
import chances.wechat.service.WechatUserService;
import chances.wechat.utils.RequestUtils;
import fastweixin.api.response.DownloadMediaResponse;
import net.coobird.thumbnailator.Thumbnails;

@RestController
@RequestMapping(path = "/photo")
public class PhotoController extends UserAbstractController {

    Logger logger = LoggerFactory.getLogger(PhotoController.class);
    
    @Autowired
    UserFileSystem userFileSystem;

    @Autowired
    UserMediaService userMediaService;
    
    @Autowired
    TokenFactory tokenFactory;
    
    @Autowired
    WechatUserService userService;
    
    ExecutorService pool = Executors.newFixedThreadPool(10);
    
    @RequestMapping(value = "/list")
    public ResultSetResponse<Object> list(HttpServletRequest request) throws Exception {
        
        String userId = RequestUtils.getParameter(request, "userId", "");
        int size = RequestUtils.getParameter(request, "pageSize", 10);
        int pageIndex = RequestUtils.getParameter(request, "pageIndex", 1);
        int status = RequestUtils.getParameter(request, "status", UserMedia.PHOTO_PASS);
        ResultSetResponse<Object> result = new ResultSetResponse<Object>();
        result.setStatus(SUCCESS);
        UserMedia userMediaParam = new UserMedia();
        userMediaParam.setOpenId(userId);
        userMediaParam.setStatus(status);
        
        try {
            List<Object> date = this.getDate(request, userMediaParam, pageIndex, size);
            if(date != null) {
                result.setResultSet(date);
                result.setPageBean(this.getUserMediaPageBean(request, userMediaParam, size, pageIndex));
            }
        } catch (Exception e) {
            result.setStatus(SYS_ERROR);
        }
        
        return result;
    }
    
    public PageBean getUserMediaPageBean(HttpServletRequest request, UserMedia userMediaParam, int size, int pageIndex) {
        PageBean result = this.getPageBean(request);
        int totalCount = this.userMediaService.getTotalCount(userMediaParam);
        result.setPageCount((int) ((totalCount - totalCount % size) / size) + 1);
        result.setCurrentPage(pageIndex);
        return result;
    }
    
    protected List<Object> getDate(HttpServletRequest request, UserMedia userMediaParam, int pageIndex, int size) {
        
        PageBean pageBean = this.getPageBean(request);
        List<Object> result = this.userMediaService.listUserMedia(userMediaParam, 0, pageBean);
        for(Object temp:result) {
            UserMedia userMedia = (UserMedia)temp;
            String path = UserFileSystem.getHashPath(userMedia.getOpenId());
            String photoUrl = this.userMediaService.getPhotoUrl();
            String basePath = photoUrl+path+"photo/";
            //System.out.println("path:"+path+",photoUrl:"+photoUrl);
            userMedia.setIcon(basePath + "icon_" + userMedia.getMediaId() + ".jpg");
            userMedia.setHd(basePath + "hd_" + userMedia.getMediaId() + ".jpg");
            userMedia.setSd(basePath + "sd_" + userMedia.getMediaId() + ".jpg");
        }
        
        return result;
    }
    
    @RequestMapping("/download")
    public ResultSetResponse<String> download(@RequestParam("app_code") String appCode,
            @RequestParam("media_id") String mediaId, @RequestParam("user_id") String openId) throws IOException {

        String accessToken = tokenFactory.getAccessToken(appCode);
        WechatUser wechatUser = userService.getWechatUser(openId);
        logger.info("download image userId:{},mediaId:{},token:{}", openId, mediaId, accessToken);
        MediaAPI mediaAPI = new MediaAPI(accessToken);
        ResultSetResponse<String> res = new ResultSetResponse<String>();
        DownloadMediaResponse downloadMediaResponse = mediaAPI.downloadMedia(mediaId);

        res.setStatus(SUCCESS);
        if (StringUtils.isNotEmpty(downloadMediaResponse.getErrcode())) {
            res.setStatus(SYS_ERROR);
        } else {
            String fileName = "/photo/src_" + mediaId + ".jpg";
            UserFile userFile = saveFile(downloadMediaResponse, openId, fileName);
            if (userFile.exists()) {
                UserMedia result = createUserMedia(wechatUser, fileName, userFile, mediaId);
                
                pool.execute(new Runnable() {
                    @Override
                    public void run() {
                        try {
                            convert(result, userFile);
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                    }
                });
            } else {
                res.setStatus(SYS_ERROR);
            }

        }
        return res;
    }

    private UserMedia createUserMedia(WechatUser wechatUser, String fileName, UserFile userFile, String mediaId)
            throws IOException {
        UserMedia result = new UserMedia();
        result.setOpenId(wechatUser.getOpenId());
        result.setMediaId(mediaId);
        Dimension dim = ImageUtils.getDimension(userFile.getFile());
        result.setHeight(dim.height);
        result.setWidth(dim.width);
        result.setType("photo");
        result.setSource(fileName);
        result.setStatus(UserMedia.PHOTO_NO_AUDIT);
        result.setNickname(wechatUser.getNickname());
        this.userMediaService.insertMedia(result);
        logger.info("save media :{}", fileName);
        return result;
    }

    private UserFile saveFile(DownloadMediaResponse downloadMediaResponse, String openId, String fileName)
            throws IOException {
        UserDirectory userdirectory = userFileSystem.getUserDirectory(openId);
        UserFile userFile = userdirectory.getUserFile(fileName);
        logger.info("save file :{}", userFile.getFile().getAbsolutePath());
        UserFile uf = userdirectory.createUserFile("photo");
        if (!uf.getFile().exists()) {
            uf.getFile().mkdirs();
        }
        OutputStream out = null;
        try {
            out = userFile.getOutputStream();
            downloadMediaResponse.writeTo(out);
            out.flush();
        } finally {
            IOUtils.closeQuietly(out);
        }
        return userFile;
    }

    public void convert(final UserMedia media, UserFile userFile) throws MalformedURLException, IOException {
        int width = media.getWidth();
        int height = media.getHeight();
        if (width <= 0 || height <= 0) {
            return;
        }
        String msgId = "" + media.getMediaId();
        File aFile = new File(userFile.getAbsolutePath());
        File parent = aFile.getParentFile();
        File icon = new File(parent, "icon_" + msgId + ".jpg");
        File hd = new File(parent, "hd_" + msgId + ".jpg");
        //File sd = new File(parent, "sd_" + msgId + ".jpg");
        try {
            int iconSize = 250;
            if (width < height) {
                Thumbnails.of(aFile).sourceRegion(0, (int) (height - width) / 2, width, width).size(iconSize, iconSize)
                        .outputFormat("jpg").toFile(icon);
            } else {
                Thumbnails.of(aFile).sourceRegion((int) (width - height) / 2, 0, height, height)
                        .size(iconSize, iconSize).outputFormat("jpg").toFile(icon);
            }
            Thumbnails.of(aFile).size(1280, 720).outputFormat("jpg").toFile(hd);

        } catch (Exception e) {
        }
        logger.info("convert media :{}", userFile.getFile().getAbsolutePath());
    }
    

    /*@RequestMapping(value = "/upload")
    public ResultSetResponse<String> download(HttpServletRequest request) throws Exception {

        String userId = RequestUtils.getParameter(request, "userId", "");
        String mediaId = RequestUtils.getParameter(request, "mediaId", "");
        String nickName = RequestUtils.getParameter(request, "nickName", "");
        String appCode = RequestUtils.getParameter(request, "appCode", "");
        
        String accessToken = tokenFactory.getAccessToken(appCode);
        //String accessToken = tokenFactory.getAccessToken();

        logger.info("download image userId:{},mediaId:{},token:{}",userId,mediaId,accessToken);
        MediaAPI mediaAPI = new MediaAPI(accessToken);
        ResultSetResponse<String> res = new ResultSetResponse<String>();
        DownloadMediaResponse downloadMediaResponse = mediaAPI.downloadMedia(mediaId);

        res.setStatus(SUCCESS);
        if (StringUtils.isNotEmpty(downloadMediaResponse.getErrcode())) {
            res.setStatus(SYS_ERROR);
        }
        logger.info("download image mediaId:{},stats:{}",userId,res.getResult());

        UserDirectory userdirectory = userFileSystem.getUserDirectory(userId);
        String uuid = UUID.randomUUID().toString().replaceAll("-", "");
        String fileName = "/photo/" + downloadMediaResponse.getFileName();
        
        
        //String fileName = "/photo/" + mediaId + ".jpg";
        UserFile userFile = userdirectory.getUserFile(fileName);
        
        logger.info("save file :{}",userFile.getFile().getAbsolutePath());

        UserFile uf = userdirectory.createUserFile("photo");
        if (!uf.getFile().exists()) {
            uf.getFile().mkdirs();
        }
        OutputStream out = null;
        try {
            out = userFile.getOutputStream();
            downloadMediaResponse.writeTo(out);
            out.flush();
        } finally {
            IOUtils.closeQuietly(out);
        }
        UserMedia result = new UserMedia();
        result.setOpenId(userId);
        result.setMediaId(uuid);
        Dimension dim = ImageUtils.getDimension(userFile.getFile());
        result.setHeight(dim.height);
        result.setWidth(dim.width);
        result.setType("photo");
        result.setSource(fileName);
        result.setStatus(UserMedia.PHOTO_NO_AUDIT);
        result.setNickname(nickName);
        this.userMediaService.insertMedia(result);
        logger.info("save media :{}",fileName);
        convert(result, userFile);
        logger.info("convert media :{}",userFile.getFile().getAbsolutePath());
        return res;
    }

    @SuppressWarnings("unused")
    public void convert(final UserMedia media, UserFile userFile) throws MalformedURLException, IOException {
        int width = media.getWidth();
        int height = media.getHeight();
        if (width <= 0 || height <= 0) {
            return;
        }
        String msgId = "" + media.getMediaId();
        File aFile = new File(userFile.getAbsolutePath());
        File parent = aFile.getParentFile();
        File icon = new File(parent, "icon_" + msgId + ".jpg");
        File hd = new File(parent, "hd_" + msgId + ".jpg");
        File sd = new File(parent, "sd_" + msgId + ".jpg");
        try {
            int iconSize = 250;
            if (width < height) {
                Thumbnails.of(aFile).sourceRegion(0, (int) (height - width) / 2, width, width).size(iconSize, iconSize)
                        .outputFormat("jpg").toFile(icon);
            } else {
                Thumbnails.of(aFile).sourceRegion((int) (width - height) / 2, 0, height, height)
                        .size(iconSize, iconSize).outputFormat("jpg").toFile(icon);
            }
            Thumbnails.of(aFile).size(1280, 720).outputFormat("jpg").toFile(hd);

        } catch (Exception e) {
        }

    }*/
    
    @RequestMapping("/remove")
    public ResultResponse<String> remove(HttpServletRequest request) {
        String mediaId = RequestUtils.getParameter(request, "mediaId", "");
        ResultResponse<String> res = new ResultResponse<String>();
        res.setStatus(SUCCESS);
        try {
            UserMedia usermedia = this.userMediaService.getMediaByMediaId(mediaId);
            usermedia.setStatus(UserMedia.PHOTO_DELETE);
            this.userMediaService.updateMedia(usermedia);
            res.setResult(mediaId);
        } catch (Exception e) {
            res.setStatus(SYS_ERROR);
        }
        return res;
    }
    
    /**
     * 批量删除预约
     * @param request
     * @return
     */
    @RequestMapping("/dels")
    public ResultSetResponse<String> delMediaByMediaIds(HttpServletRequest request) {
        String mediaIds = RequestUtils.getParameter(request, "mediaIds", "");
        ResultSetResponse<String> res = new ResultSetResponse<String>();
        res.setStatus(SUCCESS);
        try {
            if (StringUtils.isNotEmpty(mediaIds)) {
                String[] ids = mediaIds.split(",");
                this.userMediaService.delMediaByMediaIds(ids, UserMedia.PHOTO_DELETE);
            }
        } catch (Exception e) {
            res.setStatus(SYS_ERROR);
        }
        return res;
    }

}
